﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Utility
{
    public static class CalcHelper
    {
        public static string normalizeType = "根法";

        //计算节点的特征向量
        public static double[] Normalize(double[][] matrix, int take = 3)
        {
            int row = matrix.Length;
            int column = matrix[0].Length;
            double[] Sum_column = new double[column];
            double[] w = new double[row];

            if (normalizeType == "和法")
            {
                for (int i = 0; i < column; i++)
                {
                    Sum_column[i] = 0;
                    for (int j = 0; j < row; j++)
                    {
                        Sum_column[i] += matrix[j][i];
                    }
                }

                //进行归一化,计算特征向量W

                for (int i = 0; i < row; i++)
                {
                    w[i] = 0;
                    for (int j = 0; j < column; j++)
                    {
                        w[i] += matrix[i][j] / Sum_column[j];
                    }
                    w[i] /= row;
                }
            }

            if (normalizeType == "根法")
            {
                for (int i = 0; i < column; i++)
                {
                    Sum_column[i] = 0;
                    for (int j = 0; j < row; j++)
                    {
                        Sum_column[i] += matrix[j][i];
                    }
                }

                //进行归一化,计算特征向量W
                double sum = 0;
                for (int i = 0; i < row; i++)
                {
                    w[i] = 1;
                    for (int j = 0; j < column; j++)
                    {
                        w[i] *= matrix[i][j] / Sum_column[j];
                    }

                    w[i] = Math.Pow(w[i], 1.0 / row);
                    sum += w[i];
                }

                for (int i = 0; i < row; i++)
                {
                    w[i] /= sum;
                }
            }

            if (normalizeType == "幂法")
            {
                double[] w0 = new double[row];
                for (int i = 0; i < row; i++)
                {
                    w0[i] = 1.0 / row;
                }

                //一般向量W（k+1）
                double[] w1 = new double[row];
                //W（k+1）的归一化向量                
                double sum = 1.0;
                double d = 1.0;
                double delt = 0.00001;
                while (d > delt)
                {
                    d = 0.0;
                    sum = 0;

                    //获取向量
                    for (int j = 0; j < row; j++)
                    {
                        w1[j] = 0;
                        for (int k = 0; k < row; k++)
                        {
                            w1[j] += matrix[j][k] * w0[k];
                        }
                        sum += w1[j];
                    }

                    //向量归一化 
                    for (int k = 0; k < row; k++)
                    {
                        w[k] = w1[k] / sum;
                        d = Math.Max(Math.Abs(w[k] - w0[k]), d);//最大差值
                        w0[k] = w[k];//用于下次迭代使用 
                    }
                }
            }

            for (int i = 0; i < row; i++)
            {
                w[i] = Math.Round(w[i], take);
            }

            return w;
        }

        public static double[] MatrixMultiplicative(double[][] a, double[] b, int take = 2)
        {
            int len = b.Length;
            int colA, rowA, rowB, colB;
            //矩阵A行数rowA,列数colA
            rowA = len;
            colA = len;
            //矩阵B行数rowB,列数colB
            rowB = len;
            colB = 1;
            double[] c = new double[len];

            if (rowA != rowB)
            {
                //判断是否可以相乘
                Console.WriteLine("不可以相乘！！！");
                return null;
            }

            Console.WriteLine("矩阵A:\n");
            for (var i = 0; i < colA; i++)
            {
                for (var j = 0; j < rowA; j++)
                {
                    Console.Write("{0}-", a[i][j]);
                    if (j == rowA) Console.Write("\n");
                }
            }

            Console.WriteLine("矩阵B:\n");
            for (var i = 0; i < rowA; i++)
            {
                Console.Write("{0}-", b[i]);
                Console.Write("\n");
            }

            Console.WriteLine("矩阵C=A*B:\n");
            for (var i = 0; i < colA; i++)
            {
                for (var j = 0; j < 1; j++)
                {
                    for (var k = 0; k < rowA; k++)
                    {
                        c[i] = c[i] + a[i][k] * b[k];
                    }
                    Console.Write("{0}-", c[i]);
                    if (j == colB) Console.Write("\n");
                }
            }

            for (int i = 0; i < len; i++)
            {
                c[i] = Math.Round(c[i], take);
            }

            return c;
        }

        public static double[] MatrixDivide(double[] ina, double[] inb, int take = 2)
        {
            int len = ina.Length;
            double[] r = new double[len];

            for (var i = 0; i < len; i++)
            {
                r[i] = ina[i] / inb[i];
                r[i] = Math.Round(r[i], take);
                Console.Write("{0}-", r[i]);
            }

            return r;
        }

        public static double MatrixSum(double[] input)
        {
            double r = 0;
            for (var i = 0; i < input.Length; i++)
            {
                r += input[i];
            }
            r = r / input.Length;
            return r;
        }

        public static double[] ArrayNormalizeSum(double[] input, int take = 5)
        {
            double s = 0;
            double[] r = new double[input.Length];
            for (var i = 0; i < input.Length; i++)
            {
                s += input[i];
            }
            for (var i = 0; i < input.Length; i++)
            {
                r[i] = Math.Round(input[i] / s, take);
            }
            return r;
        }

        public static double Calcλmax(double[][] matrix, double[] c) {
            double r = 0;
            double[] m = MatrixMultiplicative(matrix, c);
            for (int i = 0; i < c.Length; i++) {
                r += m[i] / (c.Length * c[i]);
            }
            return r;
        }

        public static double CalcCI(double λmax, int len)
        {
            double r = 0;
            r = (λmax - len) / (len - 1);
            return Math.Round(r, 3);
        }

        public static double CalcCR(double ci, double ri=1.12)
        {
            double r = 0;
            r = ci / ri;
            return Math.Round(r, 3);
        }

        //=====常用转换=====

        public static double Fraction2Double(string str, int take = 2)
        {
            double r = 0;
            if (str.IndexOf("/") > 0)
            {
                string fenzi = str.Substring(0, str.IndexOf('/'));
                string fenmu = str.Split('/')[1];
                r = Convert.ToDouble(fenzi) / Convert.ToDouble(fenmu);
            }
            else
                r = Convert.ToDouble(str);

            return Math.Round(r, take);
        }


        public static int StrToInt(string str)
        {
            int r = 0;
            int.TryParse(str, out r);
            return r;
        }

        public static decimal StrToDec(string str)
        {
            decimal r = 0;
            decimal.TryParse(str, out r);
            return r;
        }

        public static double DoubleDefault(object obj)
        {
            double r;
            try
            {
                r = double.Parse(obj.ToString());
            }
            catch
            {
                r = 0;
            }
            return r;
        }



    }
}
